//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension FIS {
    // MARK: Enums

    public enum ExperimentActionStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        case cancelled
        case completed
        case failed
        case initiating
        case pending
        case running
        case stopped
        case stopping
        public var description: String { return self.rawValue }
    }

    public enum ExperimentStatus: String, CustomStringConvertible, Codable, _SotoSendable {
        case completed
        case failed
        case initiating
        case pending
        case running
        case stopped
        case stopping
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct Action: AWSDecodableShape {
        /// The description for the action.
        public let description: String?
        /// The ID of the action.
        public let id: String?
        /// The action parameters, if applicable.
        public let parameters: [String: ActionParameter]?
        /// The tags for the action.
        public let tags: [String: String]?
        /// The supported targets for the action.
        public let targets: [String: ActionTarget]?

        public init(description: String? = nil, id: String? = nil, parameters: [String: ActionParameter]? = nil, tags: [String: String]? = nil, targets: [String: ActionTarget]? = nil) {
            self.description = description
            self.id = id
            self.parameters = parameters
            self.tags = tags
            self.targets = targets
        }

        private enum CodingKeys: String, CodingKey {
            case description
            case id
            case parameters
            case tags
            case targets
        }
    }

    public struct ActionParameter: AWSDecodableShape {
        /// The parameter description.
        public let description: String?
        /// Indicates whether the parameter is required.
        public let required: Bool?

        public init(description: String? = nil, required: Bool? = nil) {
            self.description = description
            self.required = required
        }

        private enum CodingKeys: String, CodingKey {
            case description
            case required
        }
    }

    public struct ActionSummary: AWSDecodableShape {
        /// The description for the action.
        public let description: String?
        /// The ID of the action.
        public let id: String?
        /// The tags for the action.
        public let tags: [String: String]?
        /// The targets for the action.
        public let targets: [String: ActionTarget]?

        public init(description: String? = nil, id: String? = nil, tags: [String: String]? = nil, targets: [String: ActionTarget]? = nil) {
            self.description = description
            self.id = id
            self.tags = tags
            self.targets = targets
        }

        private enum CodingKeys: String, CodingKey {
            case description
            case id
            case tags
            case targets
        }
    }

    public struct ActionTarget: AWSDecodableShape {
        /// The resource type of the target.
        public let resourceType: String?

        public init(resourceType: String? = nil) {
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case resourceType
        }
    }

    public struct CreateExperimentTemplateActionInput: AWSEncodableShape {
        /// The ID of the action. The format of the action ID is: aws:service-name:action-type.
        public let actionId: String
        /// A description for the action.
        public let description: String?
        /// The parameters for the action, if applicable.
        public let parameters: [String: String]?
        /// The name of the action that must be completed before the current action starts. Omit this parameter to run the action at the start of the experiment.
        public let startAfter: [String]?
        /// The targets for the action.
        public let targets: [String: String]?

        public init(actionId: String, description: String? = nil, parameters: [String: String]? = nil, startAfter: [String]? = nil, targets: [String: String]? = nil) {
            self.actionId = actionId
            self.description = description
            self.parameters = parameters
            self.startAfter = startAfter
            self.targets = targets
        }

        public func validate(name: String) throws {
            try self.validate(self.actionId, name: "actionId", parent: name, max: 128)
            try self.validate(self.actionId, name: "actionId", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.description, name: "description", parent: name, max: 512)
            try self.validate(self.description, name: "description", parent: name, pattern: "^[\\s\\S]+$")
            try self.parameters?.forEach {
                try validate($0.key, name: "parameters.key", parent: name, max: 64)
                try validate($0.key, name: "parameters.key", parent: name, pattern: "^[\\S]+$")
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, max: 1024)
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, pattern: "^[\\S]+$")
            }
            try self.startAfter?.forEach {
                try validate($0, name: "startAfter[]", parent: name, max: 64)
                try validate($0, name: "startAfter[]", parent: name, pattern: "^[\\S]+$")
            }
            try self.targets?.forEach {
                try validate($0.key, name: "targets.key", parent: name, max: 64)
                try validate($0.key, name: "targets.key", parent: name, pattern: "^[\\S]+$")
                try validate($0.value, name: "targets[\"\($0.key)\"]", parent: name, max: 64)
                try validate($0.value, name: "targets[\"\($0.key)\"]", parent: name, pattern: "^[\\S]+$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case actionId
            case description
            case parameters
            case startAfter
            case targets
        }
    }

    public struct CreateExperimentTemplateLogConfigurationInput: AWSEncodableShape {
        /// The configuration for experiment logging to Amazon CloudWatch Logs.
        public let cloudWatchLogsConfiguration: ExperimentTemplateCloudWatchLogsLogConfigurationInput?
        /// The schema version.
        public let logSchemaVersion: Int
        /// The configuration for experiment logging to Amazon S3.
        public let s3Configuration: ExperimentTemplateS3LogConfigurationInput?

        public init(cloudWatchLogsConfiguration: ExperimentTemplateCloudWatchLogsLogConfigurationInput? = nil, logSchemaVersion: Int, s3Configuration: ExperimentTemplateS3LogConfigurationInput? = nil) {
            self.cloudWatchLogsConfiguration = cloudWatchLogsConfiguration
            self.logSchemaVersion = logSchemaVersion
            self.s3Configuration = s3Configuration
        }

        public func validate(name: String) throws {
            try self.cloudWatchLogsConfiguration?.validate(name: "\(name).cloudWatchLogsConfiguration")
            try self.s3Configuration?.validate(name: "\(name).s3Configuration")
        }

        private enum CodingKeys: String, CodingKey {
            case cloudWatchLogsConfiguration
            case logSchemaVersion
            case s3Configuration
        }
    }

    public struct CreateExperimentTemplateRequest: AWSEncodableShape {
        /// The actions for the experiment.
        public let actions: [String: CreateExperimentTemplateActionInput]
        /// Unique, case-sensitive identifier that you provide to ensure the idempotency of the request.
        public let clientToken: String
        /// A description for the experiment template.
        public let description: String
        /// The configuration for experiment logging.
        public let logConfiguration: CreateExperimentTemplateLogConfigurationInput?
        /// The Amazon Resource Name (ARN) of an IAM role that grants the FIS service permission to perform service actions on your behalf.
        public let roleArn: String
        /// The stop conditions.
        public let stopConditions: [CreateExperimentTemplateStopConditionInput]
        /// The tags to apply to the experiment template.
        public let tags: [String: String]?
        /// The targets for the experiment.
        public let targets: [String: CreateExperimentTemplateTargetInput]?

        public init(actions: [String: CreateExperimentTemplateActionInput], clientToken: String = CreateExperimentTemplateRequest.idempotencyToken(), description: String, logConfiguration: CreateExperimentTemplateLogConfigurationInput? = nil, roleArn: String, stopConditions: [CreateExperimentTemplateStopConditionInput], tags: [String: String]? = nil, targets: [String: CreateExperimentTemplateTargetInput]? = nil) {
            self.actions = actions
            self.clientToken = clientToken
            self.description = description
            self.logConfiguration = logConfiguration
            self.roleArn = roleArn
            self.stopConditions = stopConditions
            self.tags = tags
            self.targets = targets
        }

        public func validate(name: String) throws {
            try self.actions.forEach {
                try validate($0.key, name: "actions.key", parent: name, max: 64)
                try validate($0.key, name: "actions.key", parent: name, pattern: "^[\\S]+$")
                try $0.value.validate(name: "\(name).actions[\"\($0.key)\"]")
            }
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 1024)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.description, name: "description", parent: name, max: 512)
            try self.validate(self.description, name: "description", parent: name, pattern: "^[\\s\\S]+$")
            try self.logConfiguration?.validate(name: "\(name).logConfiguration")
            try self.validate(self.roleArn, name: "roleArn", parent: name, max: 2048)
            try self.validate(self.roleArn, name: "roleArn", parent: name, min: 20)
            try self.validate(self.roleArn, name: "roleArn", parent: name, pattern: "^[\\S]+$")
            try self.stopConditions.forEach {
                try $0.validate(name: "\(name).stopConditions[]")
            }
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[\\s\\S]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[\\s\\S]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
            try self.targets?.forEach {
                try validate($0.key, name: "targets.key", parent: name, max: 64)
                try validate($0.key, name: "targets.key", parent: name, pattern: "^[\\S]+$")
                try $0.value.validate(name: "\(name).targets[\"\($0.key)\"]")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case actions
            case clientToken
            case description
            case logConfiguration
            case roleArn
            case stopConditions
            case tags
            case targets
        }
    }

    public struct CreateExperimentTemplateResponse: AWSDecodableShape {
        /// Information about the experiment template.
        public let experimentTemplate: ExperimentTemplate?

        public init(experimentTemplate: ExperimentTemplate? = nil) {
            self.experimentTemplate = experimentTemplate
        }

        private enum CodingKeys: String, CodingKey {
            case experimentTemplate
        }
    }

    public struct CreateExperimentTemplateStopConditionInput: AWSEncodableShape {
        /// The source for the stop condition. Specify aws:cloudwatch:alarm if the stop condition is defined by a CloudWatch alarm. Specify none if there is no stop condition.
        public let source: String
        /// The Amazon Resource Name (ARN) of the CloudWatch alarm. This is required if the source is a CloudWatch alarm.
        public let value: String?

        public init(source: String, value: String? = nil) {
            self.source = source
            self.value = value
        }

        public func validate(name: String) throws {
            try self.validate(self.source, name: "source", parent: name, max: 64)
            try self.validate(self.source, name: "source", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.value, name: "value", parent: name, max: 2048)
            try self.validate(self.value, name: "value", parent: name, min: 20)
            try self.validate(self.value, name: "value", parent: name, pattern: "^[\\s\\S]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case source
            case value
        }
    }

    public struct CreateExperimentTemplateTargetInput: AWSEncodableShape {
        /// The filters to apply to identify target resources using specific attributes.
        public let filters: [ExperimentTemplateTargetInputFilter]?
        /// The resource type parameters.
        public let parameters: [String: String]?
        /// The Amazon Resource Names (ARNs) of the resources.
        public let resourceArns: [String]?
        /// The tags for the target resources.
        public let resourceTags: [String: String]?
        /// The resource type. The resource type must be supported for the specified action.
        public let resourceType: String
        /// Scopes the identified resources to a specific count of the resources at random, or a percentage of the resources. All identified resources are included in the target.   ALL - Run the action on all identified targets. This is the default.   COUNT(n) - Run the action on the specified number of targets, chosen from the identified targets at random. For example, COUNT(1) selects one of the targets.   PERCENT(n) - Run the action on the specified percentage of targets, chosen from the identified targets  at random. For example, PERCENT(25) selects 25% of the targets.
        public let selectionMode: String

        public init(filters: [ExperimentTemplateTargetInputFilter]? = nil, parameters: [String: String]? = nil, resourceArns: [String]? = nil, resourceTags: [String: String]? = nil, resourceType: String, selectionMode: String) {
            self.filters = filters
            self.parameters = parameters
            self.resourceArns = resourceArns
            self.resourceTags = resourceTags
            self.resourceType = resourceType
            self.selectionMode = selectionMode
        }

        public func validate(name: String) throws {
            try self.filters?.forEach {
                try $0.validate(name: "\(name).filters[]")
            }
            try self.parameters?.forEach {
                try validate($0.key, name: "parameters.key", parent: name, max: 64)
                try validate($0.key, name: "parameters.key", parent: name, pattern: "^[\\S]+$")
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, max: 1024)
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, pattern: "^[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+$")
            }
            try self.resourceArns?.forEach {
                try validate($0, name: "resourceArns[]", parent: name, max: 2048)
                try validate($0, name: "resourceArns[]", parent: name, min: 20)
                try validate($0, name: "resourceArns[]", parent: name, pattern: "^[\\S]+$")
            }
            try self.validate(self.resourceArns, name: "resourceArns", parent: name, max: 5)
            try self.resourceTags?.forEach {
                try validate($0.key, name: "resourceTags.key", parent: name, max: 128)
                try validate($0.key, name: "resourceTags.key", parent: name, pattern: "^[\\s\\S]+$")
                try validate($0.value, name: "resourceTags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "resourceTags[\"\($0.key)\"]", parent: name, pattern: "^[\\s\\S]*$")
            }
            try self.validate(self.resourceTags, name: "resourceTags", parent: name, max: 50)
            try self.validate(self.resourceType, name: "resourceType", parent: name, max: 128)
            try self.validate(self.resourceType, name: "resourceType", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.selectionMode, name: "selectionMode", parent: name, max: 64)
            try self.validate(self.selectionMode, name: "selectionMode", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case filters
            case parameters
            case resourceArns
            case resourceTags
            case resourceType
            case selectionMode
        }
    }

    public struct DeleteExperimentTemplateRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "id", location: .uri("id"))
        ]

        /// The ID of the experiment template.
        public let id: String

        public init(id: String) {
            self.id = id
        }

        public func validate(name: String) throws {
            try self.validate(self.id, name: "id", parent: name, max: 64)
            try self.validate(self.id, name: "id", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteExperimentTemplateResponse: AWSDecodableShape {
        /// Information about the experiment template.
        public let experimentTemplate: ExperimentTemplate?

        public init(experimentTemplate: ExperimentTemplate? = nil) {
            self.experimentTemplate = experimentTemplate
        }

        private enum CodingKeys: String, CodingKey {
            case experimentTemplate
        }
    }

    public struct Experiment: AWSDecodableShape {
        /// The actions for the experiment.
        public let actions: [String: ExperimentAction]?
        /// The time that the experiment was created.
        public let creationTime: Date?
        /// The time that the experiment ended.
        public let endTime: Date?
        /// The ID of the experiment template.
        public let experimentTemplateId: String?
        /// The ID of the experiment.
        public let id: String?
        /// The configuration for experiment logging.
        public let logConfiguration: ExperimentLogConfiguration?
        /// The Amazon Resource Name (ARN) of an IAM role that grants the FIS service permission to perform service actions on your behalf.
        public let roleArn: String?
        /// The time that the experiment started.
        public let startTime: Date?
        /// The state of the experiment.
        public let state: ExperimentState?
        /// The stop conditions for the experiment.
        public let stopConditions: [ExperimentStopCondition]?
        /// The tags for the experiment.
        public let tags: [String: String]?
        /// The targets for the experiment.
        public let targets: [String: ExperimentTarget]?

        public init(actions: [String: ExperimentAction]? = nil, creationTime: Date? = nil, endTime: Date? = nil, experimentTemplateId: String? = nil, id: String? = nil, logConfiguration: ExperimentLogConfiguration? = nil, roleArn: String? = nil, startTime: Date? = nil, state: ExperimentState? = nil, stopConditions: [ExperimentStopCondition]? = nil, tags: [String: String]? = nil, targets: [String: ExperimentTarget]? = nil) {
            self.actions = actions
            self.creationTime = creationTime
            self.endTime = endTime
            self.experimentTemplateId = experimentTemplateId
            self.id = id
            self.logConfiguration = logConfiguration
            self.roleArn = roleArn
            self.startTime = startTime
            self.state = state
            self.stopConditions = stopConditions
            self.tags = tags
            self.targets = targets
        }

        private enum CodingKeys: String, CodingKey {
            case actions
            case creationTime
            case endTime
            case experimentTemplateId
            case id
            case logConfiguration
            case roleArn
            case startTime
            case state
            case stopConditions
            case tags
            case targets
        }
    }

    public struct ExperimentAction: AWSDecodableShape {
        /// The ID of the action.
        public let actionId: String?
        /// The description for the action.
        public let description: String?
        /// The time that the action ended.
        public let endTime: Date?
        /// The parameters for the action.
        public let parameters: [String: String]?
        /// The name of the action that must be completed before this action starts.
        public let startAfter: [String]?
        /// The time that the action started.
        public let startTime: Date?
        /// The state of the action.
        public let state: ExperimentActionState?
        /// The targets for the action.
        public let targets: [String: String]?

        public init(actionId: String? = nil, description: String? = nil, endTime: Date? = nil, parameters: [String: String]? = nil, startAfter: [String]? = nil, startTime: Date? = nil, state: ExperimentActionState? = nil, targets: [String: String]? = nil) {
            self.actionId = actionId
            self.description = description
            self.endTime = endTime
            self.parameters = parameters
            self.startAfter = startAfter
            self.startTime = startTime
            self.state = state
            self.targets = targets
        }

        private enum CodingKeys: String, CodingKey {
            case actionId
            case description
            case endTime
            case parameters
            case startAfter
            case startTime
            case state
            case targets
        }
    }

    public struct ExperimentActionState: AWSDecodableShape {
        /// The reason for the state.
        public let reason: String?
        /// The state of the action.
        public let status: ExperimentActionStatus?

        public init(reason: String? = nil, status: ExperimentActionStatus? = nil) {
            self.reason = reason
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case reason
            case status
        }
    }

    public struct ExperimentCloudWatchLogsLogConfiguration: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the destination Amazon CloudWatch Logs log group.
        public let logGroupArn: String?

        public init(logGroupArn: String? = nil) {
            self.logGroupArn = logGroupArn
        }

        private enum CodingKeys: String, CodingKey {
            case logGroupArn
        }
    }

    public struct ExperimentLogConfiguration: AWSDecodableShape {
        /// The configuration for experiment logging to Amazon CloudWatch Logs.
        public let cloudWatchLogsConfiguration: ExperimentCloudWatchLogsLogConfiguration?
        /// The schema version.
        public let logSchemaVersion: Int?
        /// The configuration for experiment logging to Amazon S3.
        public let s3Configuration: ExperimentS3LogConfiguration?

        public init(cloudWatchLogsConfiguration: ExperimentCloudWatchLogsLogConfiguration? = nil, logSchemaVersion: Int? = nil, s3Configuration: ExperimentS3LogConfiguration? = nil) {
            self.cloudWatchLogsConfiguration = cloudWatchLogsConfiguration
            self.logSchemaVersion = logSchemaVersion
            self.s3Configuration = s3Configuration
        }

        private enum CodingKeys: String, CodingKey {
            case cloudWatchLogsConfiguration
            case logSchemaVersion
            case s3Configuration
        }
    }

    public struct ExperimentS3LogConfiguration: AWSDecodableShape {
        /// The name of the destination bucket.
        public let bucketName: String?
        /// The bucket prefix.
        public let prefix: String?

        public init(bucketName: String? = nil, prefix: String? = nil) {
            self.bucketName = bucketName
            self.prefix = prefix
        }

        private enum CodingKeys: String, CodingKey {
            case bucketName
            case prefix
        }
    }

    public struct ExperimentState: AWSDecodableShape {
        /// The reason for the state.
        public let reason: String?
        /// The state of the experiment.
        public let status: ExperimentStatus?

        public init(reason: String? = nil, status: ExperimentStatus? = nil) {
            self.reason = reason
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case reason
            case status
        }
    }

    public struct ExperimentStopCondition: AWSDecodableShape {
        /// The source for the stop condition.
        public let source: String?
        /// The Amazon Resource Name (ARN) of the CloudWatch alarm, if applicable.
        public let value: String?

        public init(source: String? = nil, value: String? = nil) {
            self.source = source
            self.value = value
        }

        private enum CodingKeys: String, CodingKey {
            case source
            case value
        }
    }

    public struct ExperimentSummary: AWSDecodableShape {
        /// The time that the experiment was created.
        public let creationTime: Date?
        /// The ID of the experiment template.
        public let experimentTemplateId: String?
        /// The ID of the experiment.
        public let id: String?
        /// The state of the experiment.
        public let state: ExperimentState?
        /// The tags for the experiment.
        public let tags: [String: String]?

        public init(creationTime: Date? = nil, experimentTemplateId: String? = nil, id: String? = nil, state: ExperimentState? = nil, tags: [String: String]? = nil) {
            self.creationTime = creationTime
            self.experimentTemplateId = experimentTemplateId
            self.id = id
            self.state = state
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case creationTime
            case experimentTemplateId
            case id
            case state
            case tags
        }
    }

    public struct ExperimentTarget: AWSDecodableShape {
        /// The filters to apply to identify target resources using specific attributes.
        public let filters: [ExperimentTargetFilter]?
        /// The resource type parameters.
        public let parameters: [String: String]?
        /// The Amazon Resource Names (ARNs) of the resources.
        public let resourceArns: [String]?
        /// The tags for the target resources.
        public let resourceTags: [String: String]?
        /// The resource type.
        public let resourceType: String?
        /// Scopes the identified resources to a specific count or percentage.
        public let selectionMode: String?

        public init(filters: [ExperimentTargetFilter]? = nil, parameters: [String: String]? = nil, resourceArns: [String]? = nil, resourceTags: [String: String]? = nil, resourceType: String? = nil, selectionMode: String? = nil) {
            self.filters = filters
            self.parameters = parameters
            self.resourceArns = resourceArns
            self.resourceTags = resourceTags
            self.resourceType = resourceType
            self.selectionMode = selectionMode
        }

        private enum CodingKeys: String, CodingKey {
            case filters
            case parameters
            case resourceArns
            case resourceTags
            case resourceType
            case selectionMode
        }
    }

    public struct ExperimentTargetFilter: AWSDecodableShape {
        /// The attribute path for the filter.
        public let path: String?
        /// The attribute values for the filter.
        public let values: [String]?

        public init(path: String? = nil, values: [String]? = nil) {
            self.path = path
            self.values = values
        }

        private enum CodingKeys: String, CodingKey {
            case path
            case values
        }
    }

    public struct ExperimentTemplate: AWSDecodableShape {
        /// The actions for the experiment.
        public let actions: [String: ExperimentTemplateAction]?
        /// The time the experiment template was created.
        public let creationTime: Date?
        /// The description for the experiment template.
        public let description: String?
        /// The ID of the experiment template.
        public let id: String?
        /// The time the experiment template was last updated.
        public let lastUpdateTime: Date?
        /// The configuration for experiment logging.
        public let logConfiguration: ExperimentTemplateLogConfiguration?
        /// The Amazon Resource Name (ARN) of an IAM role.
        public let roleArn: String?
        /// The stop conditions for the experiment.
        public let stopConditions: [ExperimentTemplateStopCondition]?
        /// The tags for the experiment template.
        public let tags: [String: String]?
        /// The targets for the experiment.
        public let targets: [String: ExperimentTemplateTarget]?

        public init(actions: [String: ExperimentTemplateAction]? = nil, creationTime: Date? = nil, description: String? = nil, id: String? = nil, lastUpdateTime: Date? = nil, logConfiguration: ExperimentTemplateLogConfiguration? = nil, roleArn: String? = nil, stopConditions: [ExperimentTemplateStopCondition]? = nil, tags: [String: String]? = nil, targets: [String: ExperimentTemplateTarget]? = nil) {
            self.actions = actions
            self.creationTime = creationTime
            self.description = description
            self.id = id
            self.lastUpdateTime = lastUpdateTime
            self.logConfiguration = logConfiguration
            self.roleArn = roleArn
            self.stopConditions = stopConditions
            self.tags = tags
            self.targets = targets
        }

        private enum CodingKeys: String, CodingKey {
            case actions
            case creationTime
            case description
            case id
            case lastUpdateTime
            case logConfiguration
            case roleArn
            case stopConditions
            case tags
            case targets
        }
    }

    public struct ExperimentTemplateAction: AWSDecodableShape {
        /// The ID of the action.
        public let actionId: String?
        /// A description for the action.
        public let description: String?
        /// The parameters for the action.
        public let parameters: [String: String]?
        /// The name of the action that must be completed before the current action starts.
        public let startAfter: [String]?
        /// The targets for the action.
        public let targets: [String: String]?

        public init(actionId: String? = nil, description: String? = nil, parameters: [String: String]? = nil, startAfter: [String]? = nil, targets: [String: String]? = nil) {
            self.actionId = actionId
            self.description = description
            self.parameters = parameters
            self.startAfter = startAfter
            self.targets = targets
        }

        private enum CodingKeys: String, CodingKey {
            case actionId
            case description
            case parameters
            case startAfter
            case targets
        }
    }

    public struct ExperimentTemplateCloudWatchLogsLogConfiguration: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the destination Amazon CloudWatch Logs log group.
        public let logGroupArn: String?

        public init(logGroupArn: String? = nil) {
            self.logGroupArn = logGroupArn
        }

        private enum CodingKeys: String, CodingKey {
            case logGroupArn
        }
    }

    public struct ExperimentTemplateCloudWatchLogsLogConfigurationInput: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the destination Amazon CloudWatch Logs log group.
        public let logGroupArn: String

        public init(logGroupArn: String) {
            self.logGroupArn = logGroupArn
        }

        public func validate(name: String) throws {
            try self.validate(self.logGroupArn, name: "logGroupArn", parent: name, max: 2048)
            try self.validate(self.logGroupArn, name: "logGroupArn", parent: name, min: 20)
            try self.validate(self.logGroupArn, name: "logGroupArn", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case logGroupArn
        }
    }

    public struct ExperimentTemplateLogConfiguration: AWSDecodableShape {
        /// The configuration for experiment logging to Amazon CloudWatch Logs.
        public let cloudWatchLogsConfiguration: ExperimentTemplateCloudWatchLogsLogConfiguration?
        /// The schema version.
        public let logSchemaVersion: Int?
        /// The configuration for experiment logging to Amazon S3.
        public let s3Configuration: ExperimentTemplateS3LogConfiguration?

        public init(cloudWatchLogsConfiguration: ExperimentTemplateCloudWatchLogsLogConfiguration? = nil, logSchemaVersion: Int? = nil, s3Configuration: ExperimentTemplateS3LogConfiguration? = nil) {
            self.cloudWatchLogsConfiguration = cloudWatchLogsConfiguration
            self.logSchemaVersion = logSchemaVersion
            self.s3Configuration = s3Configuration
        }

        private enum CodingKeys: String, CodingKey {
            case cloudWatchLogsConfiguration
            case logSchemaVersion
            case s3Configuration
        }
    }

    public struct ExperimentTemplateS3LogConfiguration: AWSDecodableShape {
        /// The name of the destination bucket.
        public let bucketName: String?
        /// The bucket prefix.
        public let prefix: String?

        public init(bucketName: String? = nil, prefix: String? = nil) {
            self.bucketName = bucketName
            self.prefix = prefix
        }

        private enum CodingKeys: String, CodingKey {
            case bucketName
            case prefix
        }
    }

    public struct ExperimentTemplateS3LogConfigurationInput: AWSEncodableShape {
        /// The name of the destination bucket.
        public let bucketName: String
        /// The bucket prefix.
        public let prefix: String?

        public init(bucketName: String, prefix: String? = nil) {
            self.bucketName = bucketName
            self.prefix = prefix
        }

        public func validate(name: String) throws {
            try self.validate(self.bucketName, name: "bucketName", parent: name, max: 63)
            try self.validate(self.bucketName, name: "bucketName", parent: name, min: 3)
            try self.validate(self.bucketName, name: "bucketName", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.prefix, name: "prefix", parent: name, max: 1024)
            try self.validate(self.prefix, name: "prefix", parent: name, min: 1)
            try self.validate(self.prefix, name: "prefix", parent: name, pattern: "^[\\s\\S]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case bucketName
            case prefix
        }
    }

    public struct ExperimentTemplateStopCondition: AWSDecodableShape {
        /// The source for the stop condition.
        public let source: String?
        /// The Amazon Resource Name (ARN) of the CloudWatch alarm, if applicable.
        public let value: String?

        public init(source: String? = nil, value: String? = nil) {
            self.source = source
            self.value = value
        }

        private enum CodingKeys: String, CodingKey {
            case source
            case value
        }
    }

    public struct ExperimentTemplateSummary: AWSDecodableShape {
        /// The time that the experiment template was created.
        public let creationTime: Date?
        /// The description of the experiment template.
        public let description: String?
        /// The ID of the experiment template.
        public let id: String?
        /// The time that the experiment template was last updated.
        public let lastUpdateTime: Date?
        /// The tags for the experiment template.
        public let tags: [String: String]?

        public init(creationTime: Date? = nil, description: String? = nil, id: String? = nil, lastUpdateTime: Date? = nil, tags: [String: String]? = nil) {
            self.creationTime = creationTime
            self.description = description
            self.id = id
            self.lastUpdateTime = lastUpdateTime
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case creationTime
            case description
            case id
            case lastUpdateTime
            case tags
        }
    }

    public struct ExperimentTemplateTarget: AWSDecodableShape {
        /// The filters to apply to identify target resources using specific attributes.
        public let filters: [ExperimentTemplateTargetFilter]?
        /// The resource type parameters.
        public let parameters: [String: String]?
        /// The Amazon Resource Names (ARNs) of the targets.
        public let resourceArns: [String]?
        /// The tags for the target resources.
        public let resourceTags: [String: String]?
        /// The resource type.
        public let resourceType: String?
        /// Scopes the identified resources to a specific count or percentage.
        public let selectionMode: String?

        public init(filters: [ExperimentTemplateTargetFilter]? = nil, parameters: [String: String]? = nil, resourceArns: [String]? = nil, resourceTags: [String: String]? = nil, resourceType: String? = nil, selectionMode: String? = nil) {
            self.filters = filters
            self.parameters = parameters
            self.resourceArns = resourceArns
            self.resourceTags = resourceTags
            self.resourceType = resourceType
            self.selectionMode = selectionMode
        }

        private enum CodingKeys: String, CodingKey {
            case filters
            case parameters
            case resourceArns
            case resourceTags
            case resourceType
            case selectionMode
        }
    }

    public struct ExperimentTemplateTargetFilter: AWSDecodableShape {
        /// The attribute path for the filter.
        public let path: String?
        /// The attribute values for the filter.
        public let values: [String]?

        public init(path: String? = nil, values: [String]? = nil) {
            self.path = path
            self.values = values
        }

        private enum CodingKeys: String, CodingKey {
            case path
            case values
        }
    }

    public struct ExperimentTemplateTargetInputFilter: AWSEncodableShape {
        /// The attribute path for the filter.
        public let path: String
        /// The attribute values for the filter.
        public let values: [String]

        public init(path: String, values: [String]) {
            self.path = path
            self.values = values
        }

        public func validate(name: String) throws {
            try self.validate(self.path, name: "path", parent: name, max: 256)
            try self.validate(self.path, name: "path", parent: name, pattern: "^[\\S]+$")
            try self.values.forEach {
                try validate($0, name: "values[]", parent: name, max: 128)
                try validate($0, name: "values[]", parent: name, pattern: "^[\\S]+$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case path
            case values
        }
    }

    public struct GetActionRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "id", location: .uri("id"))
        ]

        /// The ID of the action.
        public let id: String

        public init(id: String) {
            self.id = id
        }

        public func validate(name: String) throws {
            try self.validate(self.id, name: "id", parent: name, max: 128)
            try self.validate(self.id, name: "id", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetActionResponse: AWSDecodableShape {
        /// Information about the action.
        public let action: Action?

        public init(action: Action? = nil) {
            self.action = action
        }

        private enum CodingKeys: String, CodingKey {
            case action
        }
    }

    public struct GetExperimentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "id", location: .uri("id"))
        ]

        /// The ID of the experiment.
        public let id: String

        public init(id: String) {
            self.id = id
        }

        public func validate(name: String) throws {
            try self.validate(self.id, name: "id", parent: name, max: 64)
            try self.validate(self.id, name: "id", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetExperimentResponse: AWSDecodableShape {
        /// Information about the experiment.
        public let experiment: Experiment?

        public init(experiment: Experiment? = nil) {
            self.experiment = experiment
        }

        private enum CodingKeys: String, CodingKey {
            case experiment
        }
    }

    public struct GetExperimentTemplateRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "id", location: .uri("id"))
        ]

        /// The ID of the experiment template.
        public let id: String

        public init(id: String) {
            self.id = id
        }

        public func validate(name: String) throws {
            try self.validate(self.id, name: "id", parent: name, max: 64)
            try self.validate(self.id, name: "id", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetExperimentTemplateResponse: AWSDecodableShape {
        /// Information about the experiment template.
        public let experimentTemplate: ExperimentTemplate?

        public init(experimentTemplate: ExperimentTemplate? = nil) {
            self.experimentTemplate = experimentTemplate
        }

        private enum CodingKeys: String, CodingKey {
            case experimentTemplate
        }
    }

    public struct GetTargetResourceTypeRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceType", location: .uri("resourceType"))
        ]

        /// The resource type.
        public let resourceType: String

        public init(resourceType: String) {
            self.resourceType = resourceType
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceType, name: "resourceType", parent: name, max: 128)
            try self.validate(self.resourceType, name: "resourceType", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetTargetResourceTypeResponse: AWSDecodableShape {
        /// Information about the resource type.
        public let targetResourceType: TargetResourceType?

        public init(targetResourceType: TargetResourceType? = nil) {
            self.targetResourceType = targetResourceType
        }

        private enum CodingKeys: String, CodingKey {
            case targetResourceType
        }
    }

    public struct ListActionsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken"))
        ]

        /// The maximum number of results to return with a single call. To retrieve the remaining results, make another call with the returned nextToken value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListActionsResponse: AWSDecodableShape {
        /// The actions.
        public let actions: [ActionSummary]?
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?

        public init(actions: [ActionSummary]? = nil, nextToken: String? = nil) {
            self.actions = actions
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case actions
            case nextToken
        }
    }

    public struct ListExperimentTemplatesRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken"))
        ]

        /// The maximum number of results to return with a single call. To retrieve the remaining results, make another call with the returned nextToken value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListExperimentTemplatesResponse: AWSDecodableShape {
        /// The experiment templates.
        public let experimentTemplates: [ExperimentTemplateSummary]?
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?

        public init(experimentTemplates: [ExperimentTemplateSummary]? = nil, nextToken: String? = nil) {
            self.experimentTemplates = experimentTemplates
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case experimentTemplates
            case nextToken
        }
    }

    public struct ListExperimentsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken"))
        ]

        /// The maximum number of results to return with a single call. To retrieve the remaining results, make another call with the returned nextToken value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListExperimentsResponse: AWSDecodableShape {
        /// The experiments.
        public let experiments: [ExperimentSummary]?
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?

        public init(experiments: [ExperimentSummary]? = nil, nextToken: String? = nil) {
            self.experiments = experiments
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case experiments
            case nextToken
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The Amazon Resource Name (ARN) of the resource.
        public let resourceArn: String

        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// The tags for the resource.
        public let tags: [String: String]?

        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct ListTargetResourceTypesRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken"))
        ]

        /// The maximum number of results to return with a single call. To retrieve the remaining results, make another call with the returned nextToken value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?

        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTargetResourceTypesResponse: AWSDecodableShape {
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?
        /// The target resource types.
        public let targetResourceTypes: [TargetResourceTypeSummary]?

        public init(nextToken: String? = nil, targetResourceTypes: [TargetResourceTypeSummary]? = nil) {
            self.nextToken = nextToken
            self.targetResourceTypes = targetResourceTypes
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken
            case targetResourceTypes
        }
    }

    public struct StartExperimentRequest: AWSEncodableShape {
        /// Unique, case-sensitive identifier that you provide to ensure the idempotency of the request.
        public let clientToken: String
        /// The ID of the experiment template.
        public let experimentTemplateId: String
        /// The tags to apply to the experiment.
        public let tags: [String: String]?

        public init(clientToken: String = StartExperimentRequest.idempotencyToken(), experimentTemplateId: String, tags: [String: String]? = nil) {
            self.clientToken = clientToken
            self.experimentTemplateId = experimentTemplateId
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 1024)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.experimentTemplateId, name: "experimentTemplateId", parent: name, max: 64)
            try self.validate(self.experimentTemplateId, name: "experimentTemplateId", parent: name, pattern: "^[\\S]+$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[\\s\\S]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[\\s\\S]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken
            case experimentTemplateId
            case tags
        }
    }

    public struct StartExperimentResponse: AWSDecodableShape {
        /// Information about the experiment.
        public let experiment: Experiment?

        public init(experiment: Experiment? = nil) {
            self.experiment = experiment
        }

        private enum CodingKeys: String, CodingKey {
            case experiment
        }
    }

    public struct StopExperimentRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "id", location: .uri("id"))
        ]

        /// The ID of the experiment.
        public let id: String

        public init(id: String) {
            self.id = id
        }

        public func validate(name: String) throws {
            try self.validate(self.id, name: "id", parent: name, max: 64)
            try self.validate(self.id, name: "id", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct StopExperimentResponse: AWSDecodableShape {
        /// Information about the experiment.
        public let experiment: Experiment?

        public init(experiment: Experiment? = nil) {
            self.experiment = experiment
        }

        private enum CodingKeys: String, CodingKey {
            case experiment
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The Amazon Resource Name (ARN) of the resource.
        public let resourceArn: String
        /// The tags for the resource.
        public let tags: [String: String]

        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^[\\S]+$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[\\s\\S]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[\\s\\S]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct TargetResourceType: AWSDecodableShape {
        /// A description of the resource type.
        public let description: String?
        /// The parameters for the resource type.
        public let parameters: [String: TargetResourceTypeParameter]?
        /// The resource type.
        public let resourceType: String?

        public init(description: String? = nil, parameters: [String: TargetResourceTypeParameter]? = nil, resourceType: String? = nil) {
            self.description = description
            self.parameters = parameters
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case description
            case parameters
            case resourceType
        }
    }

    public struct TargetResourceTypeParameter: AWSDecodableShape {
        /// A description of the parameter.
        public let description: String?
        /// Indicates whether the parameter is required.
        public let required: Bool?

        public init(description: String? = nil, required: Bool? = nil) {
            self.description = description
            self.required = required
        }

        private enum CodingKeys: String, CodingKey {
            case description
            case required
        }
    }

    public struct TargetResourceTypeSummary: AWSDecodableShape {
        /// A description of the resource type.
        public let description: String?
        /// The resource type.
        public let resourceType: String?

        public init(description: String? = nil, resourceType: String? = nil) {
            self.description = description
            self.resourceType = resourceType
        }

        private enum CodingKeys: String, CodingKey {
            case description
            case resourceType
        }
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn")),
            AWSMemberEncoding(label: "tagKeys", location: .querystring("tagKeys"))
        ]

        /// The Amazon Resource Name (ARN) of the resource.
        public let resourceArn: String
        /// The tag keys to remove.
        public let tagKeys: [String]?

        public init(resourceArn: String, tagKeys: [String]? = nil) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^[\\S]+$")
            try self.tagKeys?.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^[\\s\\S]+$")
            }
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateExperimentTemplateActionInputItem: AWSEncodableShape {
        /// The ID of the action.
        public let actionId: String?
        /// A description for the action.
        public let description: String?
        /// The parameters for the action, if applicable.
        public let parameters: [String: String]?
        /// The name of the action that must be completed before the current action starts. Omit this parameter to run the action at the start of the experiment.
        public let startAfter: [String]?
        /// The targets for the action.
        public let targets: [String: String]?

        public init(actionId: String? = nil, description: String? = nil, parameters: [String: String]? = nil, startAfter: [String]? = nil, targets: [String: String]? = nil) {
            self.actionId = actionId
            self.description = description
            self.parameters = parameters
            self.startAfter = startAfter
            self.targets = targets
        }

        public func validate(name: String) throws {
            try self.validate(self.actionId, name: "actionId", parent: name, max: 128)
            try self.validate(self.actionId, name: "actionId", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.description, name: "description", parent: name, max: 512)
            try self.validate(self.description, name: "description", parent: name, pattern: "^[\\s\\S]+$")
            try self.parameters?.forEach {
                try validate($0.key, name: "parameters.key", parent: name, max: 64)
                try validate($0.key, name: "parameters.key", parent: name, pattern: "^[\\S]+$")
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, max: 1024)
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, pattern: "^[\\S]+$")
            }
            try self.startAfter?.forEach {
                try validate($0, name: "startAfter[]", parent: name, max: 64)
                try validate($0, name: "startAfter[]", parent: name, pattern: "^[\\S]+$")
            }
            try self.targets?.forEach {
                try validate($0.key, name: "targets.key", parent: name, max: 64)
                try validate($0.key, name: "targets.key", parent: name, pattern: "^[\\S]+$")
                try validate($0.value, name: "targets[\"\($0.key)\"]", parent: name, max: 64)
                try validate($0.value, name: "targets[\"\($0.key)\"]", parent: name, pattern: "^[\\S]+$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case actionId
            case description
            case parameters
            case startAfter
            case targets
        }
    }

    public struct UpdateExperimentTemplateLogConfigurationInput: AWSEncodableShape {
        /// The configuration for experiment logging to Amazon CloudWatch Logs.
        public let cloudWatchLogsConfiguration: ExperimentTemplateCloudWatchLogsLogConfigurationInput?
        /// The schema version.
        public let logSchemaVersion: Int?
        /// The configuration for experiment logging to Amazon S3.
        public let s3Configuration: ExperimentTemplateS3LogConfigurationInput?

        public init(cloudWatchLogsConfiguration: ExperimentTemplateCloudWatchLogsLogConfigurationInput? = nil, logSchemaVersion: Int? = nil, s3Configuration: ExperimentTemplateS3LogConfigurationInput? = nil) {
            self.cloudWatchLogsConfiguration = cloudWatchLogsConfiguration
            self.logSchemaVersion = logSchemaVersion
            self.s3Configuration = s3Configuration
        }

        public func validate(name: String) throws {
            try self.cloudWatchLogsConfiguration?.validate(name: "\(name).cloudWatchLogsConfiguration")
            try self.s3Configuration?.validate(name: "\(name).s3Configuration")
        }

        private enum CodingKeys: String, CodingKey {
            case cloudWatchLogsConfiguration
            case logSchemaVersion
            case s3Configuration
        }
    }

    public struct UpdateExperimentTemplateRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "id", location: .uri("id"))
        ]

        /// The actions for the experiment.
        public let actions: [String: UpdateExperimentTemplateActionInputItem]?
        /// A description for the template.
        public let description: String?
        /// The ID of the experiment template.
        public let id: String
        /// The configuration for experiment logging.
        public let logConfiguration: UpdateExperimentTemplateLogConfigurationInput?
        /// The Amazon Resource Name (ARN) of an IAM role that grants the FIS service permission to perform service actions on your behalf.
        public let roleArn: String?
        /// The stop conditions for the experiment.
        public let stopConditions: [UpdateExperimentTemplateStopConditionInput]?
        /// The targets for the experiment.
        public let targets: [String: UpdateExperimentTemplateTargetInput]?

        public init(actions: [String: UpdateExperimentTemplateActionInputItem]? = nil, description: String? = nil, id: String, logConfiguration: UpdateExperimentTemplateLogConfigurationInput? = nil, roleArn: String? = nil, stopConditions: [UpdateExperimentTemplateStopConditionInput]? = nil, targets: [String: UpdateExperimentTemplateTargetInput]? = nil) {
            self.actions = actions
            self.description = description
            self.id = id
            self.logConfiguration = logConfiguration
            self.roleArn = roleArn
            self.stopConditions = stopConditions
            self.targets = targets
        }

        public func validate(name: String) throws {
            try self.actions?.forEach {
                try validate($0.key, name: "actions.key", parent: name, max: 64)
                try validate($0.key, name: "actions.key", parent: name, pattern: "^[\\S]+$")
                try $0.value.validate(name: "\(name).actions[\"\($0.key)\"]")
            }
            try self.validate(self.description, name: "description", parent: name, max: 512)
            try self.validate(self.description, name: "description", parent: name, pattern: "^[\\s\\S]+$")
            try self.validate(self.id, name: "id", parent: name, max: 64)
            try self.validate(self.id, name: "id", parent: name, pattern: "^[\\S]+$")
            try self.logConfiguration?.validate(name: "\(name).logConfiguration")
            try self.validate(self.roleArn, name: "roleArn", parent: name, max: 2048)
            try self.validate(self.roleArn, name: "roleArn", parent: name, min: 20)
            try self.validate(self.roleArn, name: "roleArn", parent: name, pattern: "^[\\S]+$")
            try self.stopConditions?.forEach {
                try $0.validate(name: "\(name).stopConditions[]")
            }
            try self.targets?.forEach {
                try validate($0.key, name: "targets.key", parent: name, max: 64)
                try validate($0.key, name: "targets.key", parent: name, pattern: "^[\\S]+$")
                try $0.value.validate(name: "\(name).targets[\"\($0.key)\"]")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case actions
            case description
            case logConfiguration
            case roleArn
            case stopConditions
            case targets
        }
    }

    public struct UpdateExperimentTemplateResponse: AWSDecodableShape {
        /// Information about the experiment template.
        public let experimentTemplate: ExperimentTemplate?

        public init(experimentTemplate: ExperimentTemplate? = nil) {
            self.experimentTemplate = experimentTemplate
        }

        private enum CodingKeys: String, CodingKey {
            case experimentTemplate
        }
    }

    public struct UpdateExperimentTemplateStopConditionInput: AWSEncodableShape {
        /// The source for the stop condition. Specify aws:cloudwatch:alarm if the stop condition is defined by a CloudWatch alarm. Specify none if there is no stop condition.
        public let source: String
        /// The Amazon Resource Name (ARN) of the CloudWatch alarm.
        public let value: String?

        public init(source: String, value: String? = nil) {
            self.source = source
            self.value = value
        }

        public func validate(name: String) throws {
            try self.validate(self.source, name: "source", parent: name, max: 64)
            try self.validate(self.source, name: "source", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.value, name: "value", parent: name, max: 2048)
            try self.validate(self.value, name: "value", parent: name, min: 20)
            try self.validate(self.value, name: "value", parent: name, pattern: "^[\\s\\S]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case source
            case value
        }
    }

    public struct UpdateExperimentTemplateTargetInput: AWSEncodableShape {
        /// The filters to apply to identify target resources using specific attributes.
        public let filters: [ExperimentTemplateTargetInputFilter]?
        /// The resource type parameters.
        public let parameters: [String: String]?
        /// The Amazon Resource Names (ARNs) of the targets.
        public let resourceArns: [String]?
        /// The tags for the target resources.
        public let resourceTags: [String: String]?
        /// The resource type. The resource type must be supported for the specified action.
        public let resourceType: String
        /// Scopes the identified resources to a specific count or percentage.
        public let selectionMode: String

        public init(filters: [ExperimentTemplateTargetInputFilter]? = nil, parameters: [String: String]? = nil, resourceArns: [String]? = nil, resourceTags: [String: String]? = nil, resourceType: String, selectionMode: String) {
            self.filters = filters
            self.parameters = parameters
            self.resourceArns = resourceArns
            self.resourceTags = resourceTags
            self.resourceType = resourceType
            self.selectionMode = selectionMode
        }

        public func validate(name: String) throws {
            try self.filters?.forEach {
                try $0.validate(name: "\(name).filters[]")
            }
            try self.parameters?.forEach {
                try validate($0.key, name: "parameters.key", parent: name, max: 64)
                try validate($0.key, name: "parameters.key", parent: name, pattern: "^[\\S]+$")
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, max: 1024)
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "parameters[\"\($0.key)\"]", parent: name, pattern: "^[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+$")
            }
            try self.resourceArns?.forEach {
                try validate($0, name: "resourceArns[]", parent: name, max: 2048)
                try validate($0, name: "resourceArns[]", parent: name, min: 20)
                try validate($0, name: "resourceArns[]", parent: name, pattern: "^[\\S]+$")
            }
            try self.validate(self.resourceArns, name: "resourceArns", parent: name, max: 5)
            try self.resourceTags?.forEach {
                try validate($0.key, name: "resourceTags.key", parent: name, max: 128)
                try validate($0.key, name: "resourceTags.key", parent: name, pattern: "^[\\s\\S]+$")
                try validate($0.value, name: "resourceTags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "resourceTags[\"\($0.key)\"]", parent: name, pattern: "^[\\s\\S]*$")
            }
            try self.validate(self.resourceTags, name: "resourceTags", parent: name, max: 50)
            try self.validate(self.resourceType, name: "resourceType", parent: name, max: 128)
            try self.validate(self.resourceType, name: "resourceType", parent: name, pattern: "^[\\S]+$")
            try self.validate(self.selectionMode, name: "selectionMode", parent: name, max: 64)
            try self.validate(self.selectionMode, name: "selectionMode", parent: name, pattern: "^[\\S]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case filters
            case parameters
            case resourceArns
            case resourceTags
            case resourceType
            case selectionMode
        }
    }
}

// MARK: - Errors

/// Error enum for FIS
public struct FISErrorType: AWSErrorType {
    enum Code: String {
        case conflictException = "ConflictException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize FIS
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// The request could not be processed because of a conflict.
    public static var conflictException: Self { .init(.conflictException) }
    /// The specified resource cannot be found.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// You have exceeded your service quota.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The specified input is not valid, or fails to satisfy the constraints for the request.
    public static var validationException: Self { .init(.validationException) }
}

extension FISErrorType: Equatable {
    public static func == (lhs: FISErrorType, rhs: FISErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension FISErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
